const path = require('path');
// gzip
const CompressionWebpackPlugin = require('compression-webpack-plugin');

const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

const { assetsDir, outputDir, publicPath, isPord, isDev, name, port } = require('./settings');

function resolve(dir) {
  return path.resolve(__dirname, dir);
}

module.exports = {
  // 资源路径目录
  assetsDir,
  // 资源路径前缀
  publicPath,
  // 打包输出文件目录：默认 dist
  outputDir,
  lintOnSave: !isPord,
  // 如果你不需要生产环境的 source map，可以将其设置为 false 以加速生产环境构建。
  productionSourceMap: false,

  devServer: {
    port,
    open: false,
    progress: true,
    overlay: {
      warnings: false,
      errors: true
    },
    before() {
      if (isDev) {
        require('./mock/mock-server.js');
      }
    }
    // proxy: {
    //   '/api': {
    //     target: process.env.VUE_APP_BASE_API,
    //     ws: true,
    //     changeOrigin: true,
    //     pathRewrite: {
    //       '^/api': '/'
    //     }
    //   }
    // }
  },
  css: {
    loaderOptions: {
      less: {
        modifyVars: {
          hack: `true; @import "${resolve('src/styles/vantTheme.less')}";`
        }
      }
    }
  },
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'less',
      patterns: [resolve('src/styles/mixins.less'), resolve('src/styles/var.less')]
    }
  },
  configureWebpack: () => {
    // 设置项目名称
    const options = {
      name,
      resolve: {
        // 路径别名
        alias: {
          '@': resolve('src')
        },
        symlinks: true
      },
      // 配置以下文件从 webpack输出的 bundle 中排除依赖
      externals: {
        vue: 'Vue',
        'vue-router': 'VueRouter',
        vuex: 'Vuex',
        axios: 'axios'
      }
    };
    if (isPord) {
      options.plugins = [
        // Gzip
        new CompressionWebpackPlugin({
          filename: '[path].gz[query]', // 目标资源名称
          algorithm: 'gzip',
          test: productionGzipExtensions, // 处理所有匹配此 {RegExp} 的资源
          threshold: 10240, // 只处理比这个值大的资源。按字节计算(楼主设置10K以上进行压缩)
          minRatio: 0.8 // 只有压缩率比这个值小的资源才会被处理
        })
      ];
    }
    return options;
  },
  chainWebpack: (config) => {
    config.plugins.delete('preload');
    config.plugins.delete('prefetch');

    // 如果组件库需要按需加载，不要使用 cdn
    const cdn = {
      js: [
        '//unpkg.com/vue@2.6.14/dist/vue.min.js',
        '//unpkg.com/vue-router@3.5.3/dist/vue-router.min.js',
        '//unpkg.com/vuex@3.6.2/dist/vuex.min.js',
        '//unpkg.com/axios@0.24.0/dist/axios.min.js'
      ]
    };

    // 向 webpack-html-plugin 注入 cdn
    config.plugin('html').tap((args) => {
      // html中添加cdn
      args[0].cdn = cdn;
      return args;
    });

    // https://webpack.js.org/configuration/devtool/#development
    config.when(!isPord, (config) => config.devtool('cheap-source-map'));

    // set svg-sprite-loader
    config.module.rule('svg').exclude.add(resolve('src/icons')).end();
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()
      .use('svgo-loader')
      .loader('svgo-loader')
      .options({
        plugins: [
          {
            name: 'removeAttrs',
            params: {
              attrs: ['fill', 'fill-rule']
            }
          }
        ]
      });

    config.when(isPord, (config) => {
      config
        .plugin('ScriptExtHtmlWebpackPlugin')
        .after('html')
        .use('script-ext-html-webpack-plugin', [
          {
            // 将 runtime 作为内联引入不单独存在
            inline: /runtime\..*\.js$/
          }
        ])
        .end();

      // 分割代码
      config.optimization.splitChunks({
        chunks: 'all',
        cacheGroups: {
          // cacheGroups 下可以可以配置多个组，每个组根据test设置条件，符合test条件的模块
          commons: {
            name: 'chunk-commons',
            test: resolve('src/components'),
            //  被至少用三次以上打包分离
            minChunks: 3,
            // 优先级
            priority: 5,
            // 表示是否使用已有的 chunk，如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了，那么将不会重新生成新的。
            reuseExistingChunk: true
          },
          libs: {
            name: 'chunk-libs',
            test: /[\\/]node_modules[\\/]/,
            priority: 10
            // 只打包初始时依赖的第三方
            // chunks: 'initial'
          },
          vantUI: {
            // 单独将 vantUI 拆包
            name: 'chunk-vantUI',
            // 数字大权重到，满足多个 cacheGroups 的条件时候分到权重高的
            priority: 20,
            test: /[\\/]node_modules[\\/]_?vant(.*)/
          }
        }
      });

      config.optimization.runtimeChunk('single');
    });
  }
};
